/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package hu.tothgya.timetable.elvira;

import hu.tothgya.timetable.Connection;
import hu.tothgya.timetable.Journey;
import hu.tothgya.timetable.Timetable;
import hu.tothgya.timetable.utils.StopSorter;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLEncoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/**
 *
 * @author tothgya
 */
public class TimetableFactory extends hu.tothgya.timetable.TimetableFactory {

    public List<Journey> journeys = new LinkedList<Journey>();

    public TimetableFactory(String start, String destination, Calendar date) {
        try {
            this.start = start;
            this.destination = destination;
            this.time = date;
            DateFormat df = new SimpleDateFormat("yy.MM.dd");
            this.start = URLEncoder.encode(URLEncoder.encode(start));
            this.destination = URLEncoder.encode(URLEncoder.encode(destination));
            String urlstr = "http://wap.elvira.hu/elvira.dll/wuf?i=" + this.start
                    + "&e=" + this.destination
                    + "&d=" + df.format(this.time.getTime())
                    + "&mikor=-1&at=0&ai=0&isz=0&from=1";

            int fromnum = 0;

            do {
                // System.out.println(urlstr);
                // URL url = new URL("http://wap.elvira.hu/elvira.dll/wuf?i=Debrecen&e=Ny%25C3%25ADregyh%25C3%25A1za&d=10.01.17&mikor=-1&at=0&ai=0&isz=0&from=1");
                URL url = new URL(urlstr);
                urlstr = null;
                InputStream stream = url.openStream();

                DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
                Document d = builder.parse(stream);
                NodeList nodelist = d.getElementsByTagName("a");



                // for(NodeListIterator i = new NodeListIterator(nodelist))
                for (int i = 0; i < nodelist.getLength(); i++) {
                    Node n = nodelist.item(i);
                    String journeylink = ((Element) n).getAttribute("href");
                    if (journeylink.contains("&from=")) {
                        String[] params = journeylink.split("\\?")[1].split("&");
                        for (int j = 0; j < params.length; j++) {
                            String[] parampair = params[j].split("=");
                            if (parampair[0].equals("from")) {
                                int v = Integer.parseInt(parampair[1]);
                                if (v > fromnum) {
                                    fromnum = v;
                                    urlstr = journeylink;
                                }
                            }
                        }
                    } else {
                        Journey journey = new hu.tothgya.timetable.elvira.Journey(start, destination, journeylink, n.getTextContent(), date);
                        journeys.add(journey);
                    }
                }
            } while (urlstr != null);
        } catch (SAXException ex) {
            ex.printStackTrace(System.out);
        } catch (IOException ioe) {
            ioe.printStackTrace(System.out);
        } catch (ParserConfigurationException pce) {
            pce.printStackTrace(System.out);
        }


    }

    @Override
    public List<Journey> getJourneys() {
        return journeys;
    }

    @Override
    public Timetable getJourneyTimetable() {
        Timetable table = new Timetable();

        for (Journey j : journeys) {
            boolean startAdded = false;
            boolean destinationAdded = false;

            int maxTimes = 0;
            for (String stop : table.rows.keySet()) {
                ArrayList<Calendar> times = table.rows.get(stop);
                maxTimes = Math.max(maxTimes, times.size());
                if (j.start.equals(stop)) {
                    times.add(j.leave);
                    startAdded = true;
                    maxTimes = Math.max(maxTimes, times.size());
                } else if (j.destination.equals(stop)) {
                    times.add(j.arrive);
                    destinationAdded = true;
                    maxTimes = Math.max(maxTimes, times.size());
                } else {
                    times.add(null);
                }
            }
            if (!startAdded && !destinationAdded) {
                for (ArrayList<Calendar> times : table.rows.values()) {
                    times.add(null);
                }
                ArrayList<Calendar> startTimes = new ArrayList<Calendar>();
                ArrayList<Calendar> arriveTimes = new ArrayList<Calendar>();
                for (int i = 0; i < maxTimes; i++) {
                    startTimes.add(null);
                    arriveTimes.add(null);
                }
                startTimes.add(j.leave);
                arriveTimes.add(j.arrive);
                LinkedHashMap<String, ArrayList<Calendar>> newTable = new LinkedHashMap<String, ArrayList<Calendar>>();
                newTable.put(j.start, startTimes);
                newTable.putAll(table.rows);
                newTable.put(j.destination, arriveTimes);
                table.rows = newTable;
            } else if (!startAdded) {
                for (ArrayList<Calendar> times : table.rows.values()) {
                    while (times.size() < maxTimes) {
                        times.add(null);
                    }
                }
                ArrayList<Calendar> startTimes = new ArrayList<Calendar>();
                for (int i = 0; i < maxTimes - 1; i++) {
                    startTimes.add(null);
                }
                startTimes.add(j.leave);
                LinkedHashMap<String, ArrayList<Calendar>> newTable = new LinkedHashMap<String, ArrayList<Calendar>>();
                newTable.put(j.start, startTimes);
                newTable.putAll(table.rows);
                table.rows = newTable;
            } else if (!destinationAdded) {
                for (ArrayList<Calendar> times : table.rows.values()) {
                    while (times.size() < maxTimes) {
                        times.add(null);
                    }
                }
                ArrayList<Calendar> arriveTimes = new ArrayList<Calendar>();
                for (int i = 0; i < maxTimes - 1; i++) {
                    arriveTimes.add(null);
                }
                arriveTimes.add(j.leave);
                table.rows.put(j.destination, arriveTimes);
            }
        }
        return table;
    }

    @Override
    public Timetable getConnectionTimeTable() {
        Timetable table = new Timetable();

        StopSorter ss = new StopSorter();
        for (Journey journey : journeys) {
            ss.addConnection(journey.connections);
        }

        List<String> stops = ss.sort();

        table.rows.put(stops.get(0) + " i", new ArrayList<Calendar>());
        for(int i = 1; i < stops.size() - 1; i++) {
            table.rows.put(stops.get(i) + " e", new ArrayList<Calendar>());
            table.rows.put(stops.get(i) + " i", new ArrayList<Calendar>());
        }
        table.rows.put(stops.get(stops.size() - 1) + " e", new ArrayList<Calendar>());

        for (Journey journey : journeys) {

            for(ArrayList<Calendar> t: table.rows.values())
            {
                t.add(null);
            }

            for (Connection connection : journey.connections) {
                ArrayList<Calendar> t = null;
                try {
                    t = table.rows.get(connection.start + " i");
                    t.set(t.size() - 1, connection.leave);
                } catch (NullPointerException npe) {
                    System.err.println("Start not found: " + connection.destination);
                }
                try {
                    t = table.rows.get(connection.destination + " e");
                    t.set(t.size() - 1, connection.arrive);
                } catch(NullPointerException npe) {
                    System.err.println("Destination not found: " + connection.destination);
                }
            }
        }
 
 
        return table;
    }
}
